﻿/*
	Class Description: this panel displays system information such as 
	OS's name, FlashPlayer's version, memory used,... It also has a line
	graph framerate monitor which reflects the performance of the running
	Flash file.
	------------------------------------------------------------------------
	                          APACHE LICENSE
	------------------------------------------------------------------------
	Copyright 2010 Vu Thien Nguyen Phong
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/

package com.minidebugger {
	import flash.display.Sprite;
	import flash.events.Event;
	import com.minidebugger.gui.Panel;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.system.Capabilities;
	import flash.system.System;
	import flash.utils.getTimer;
	import com.minidebugger.gui.LineGraph;

	public class FPSPanel extends Sprite {
		// FPSPanel's constants
		private const PANEL_WIDTH:int = 200;
		private const PANEL_HEIGHT:int = 300;
		private const PANEL_TITLE:String = "MiniDebugger >>> FPS Panel";
		private const DELTA_X:int = 20; // the change in x postion of graph's lines over time
		
		// GUI's elements of the FPSPanel
		private var panel:Panel;
		private var sys_txt:TextField;
		private var fps_txt:TextField;
		private var lineGraph:LineGraph;
		
		// variables used to calculate framerate
		private var frames:uint;
		private var old:uint;
		private var now:uint;
		private var fps:Number;
		private var oldFps:Number;
		
		// lines used in graph
		private var whiteLine:int;
		private var blueLine:int;
		// the y-position range in which line's dot was displayed on lineGraph object
		private var displayRange:Number; 
		private var currentX:int = 0; // the initial position of the blue line
		
		public function FPSPanel() {
			addEventListener(Event.ADDED_TO_STAGE,init);
		}
		
		private function init(e:Event):void{
			removeEventListener(Event.ADDED_TO_STAGE,init);
			
			// entry point
			setupFPSPanel();
			addEventListener(Event.ENTER_FRAME,tick);
			old = getTimer();
			fps = stage.frameRate;
			oldFps = stage.frameRate;
		}
		
		private function setupFPSPanel():void{
			// adding the base panel to FPSPanel
			panel = new Panel(PANEL_TITLE,PANEL_WIDTH,PANEL_HEIGHT);
			addChild(panel);
			
			// adding the textbox to show system information
			var sys_tf:TextFormat = new TextFormat();
			sys_tf.font = "Arial";
			sys_tf.size = 10;
			sys_tf.color = 0xffaaaaaa;
			
			sys_txt = new TextField();
			sys_txt.autoSize = "left";
			sys_txt.defaultTextFormat = sys_tf;
			sys_txt.text = "::[OS] - "+Capabilities.os+"\n::[FlashPlayer] - "+Capabilities.version+"\n::[Flash Debugger] - "+Capabilities.isDebugger;
			sys_txt.x = 5;
			sys_txt.y = 20;
			
			panel.addChild(sys_txt);
			
			// adding textbox showing memory used + fps information
			var fps_tf:TextFormat = new TextFormat();
			fps_tf.font = "Arial";
			fps_tf.size = 10;
			fps_tf.color = 0xff86daec;
			fps_tf.bold = true;
			
			fps_txt = new TextField();
			fps_txt.autoSize = "left";
			fps_txt.defaultTextFormat = fps_tf;
			fps_txt.text=">>>Memory ["+(System.totalMemory/1024/1024).toFixed(2)+"Mb]["+stage.frameRate+"fps/"+stage.frameRate+"fps]";
			fps_txt.x = 5;
			fps_txt.y = 70;
			
			panel.addChild(fps_txt);
			
			// adding the line graph to moditor frame rate along time
			lineGraph = new LineGraph(PANEL_WIDTH-10,PANEL_HEIGHT-fps_txt.y - 25);
			lineGraph.x = 5;
			lineGraph.y = fps_txt.y + 20;
			
			panel.addChild(lineGraph);
			addMonitorLines();
		}
		
		// add two lines to the graphs to reflect Flash performance
		private function addMonitorLines():void{
			whiteLine = lineGraph.addLine(0xffffff);
			blueLine = lineGraph.addLine(0xff86daec);
			
			displayRange = lineGraph.height - 30;
			// draw white line which is the theory frame rate
			lineGraph.moveLineTo(whiteLine,0,lineGraph.height - displayRange);
			lineGraph.drawLineTo(whiteLine,lineGraph.width,lineGraph.height - displayRange);
			lineGraph.addText(whiteLine,stage.frameRate+"fps",-20,-10);
			
			// initialize the blueLine - represent framerate - which will be update overtime
			lineGraph.moveLineTo(blueLine,0,lineGraph.height - displayRange);
			lineGraph.drawNode(blueLine);
		}
		
		private function tick(e:Event):void{
			if (fps_txt){
				now = getTimer();
				if (now-1000>old){
					fps = frames/(now-old)*1000;
					fps_txt.text=">>>Memory ["+(System.totalMemory/1024/1024).toFixed(2)+"Mb]["+fps.toFixed(0)+"fps/"+stage.frameRate+"fps]";
					updateLineGraph(fps);
					old = now;
					frames = 0;
				}
				else
					frames++;
			}
		}
		
		// drawing new status of the lineGraph
		private function updateLineGraph(fps:Number):void{
			if (currentX+DELTA_X<=PANEL_WIDTH-10){
				currentX += DELTA_X;
				var currentY:Number = lineGraph.height - fps*displayRange/stage.frameRate;
				if (currentY > PANEL_HEIGHT-fps_txt.y - 25)
					currentY = PANEL_HEIGHT-fps_txt.y - 25;
					
				lineGraph.drawLineTo(blueLine,currentX,currentY);
				lineGraph.drawNode(blueLine);
				if (Math.abs(fps-oldFps)>1){
					if (fps < 2)
						lineGraph.addText(blueLine,fps.toFixed(2),0,-10);
					else{	
						if (oldFps < fps)
							lineGraph.addText(blueLine,fps.toFixed(2),0,-10);
						else	
							lineGraph.addText(blueLine,fps.toFixed(2),0,10);
					}
					oldFps = fps;	
				}
			}
			else{
				lineGraph.clearLine(blueLine);
				currentX = 0;
				//fps = oldFps = stage.frameRate;
				var tmpY:Number = lineGraph.height - fps*displayRange/stage.frameRate;
				if (tmpY > PANEL_HEIGHT-fps_txt.y - 25)
					tmpY =  PANEL_HEIGHT-fps_txt.y - 25;
					
				lineGraph.moveLineTo(blueLine,0,tmpY);
				if (tmpY > lineGraph.height - displayRange+20)
					lineGraph.addText(blueLine,fps.toFixed(2),10,-15);
				else	
					lineGraph.addText(blueLine,fps.toFixed(2),10,10);
				lineGraph.drawNode(blueLine);
			}
		}
	}
}
